#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ERROR -1
#define true 1
#define false 0

typedef int ElementType;
typedef enum { addq, delq, end } Operation;

typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode {
    ElementType *Data;  /* 存储元素的数组   */
    Position Front;     /* 队列的头、尾指针 */
    int Count;          /* 队列中元素个数   */
    int MaxSize;        /* 队列最大容量     */
};
typedef PtrToQNode Queue;

Queue CreateQueue( int MaxSize )
{
    Queue Q = (Queue)malloc(sizeof(struct QNode));
    Q->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    Q->Front = 0;
    Q->Count = 0;
    Q->MaxSize = MaxSize;
    return Q;
}//此处没有多开辟一个元素位置

bool AddQ( Queue Q, ElementType X );
ElementType DeleteQ( Queue Q );

Operation GetOp();

int main()
{
    ElementType X;
    Queue Q;
    int N, done = 0;

    scanf("%d", &N);
    Q = CreateQueue(N);
    while ( !done ) {
        switch( GetOp() ) {
        case addq:
            scanf("%d", &X);
            AddQ(Q, X);
            break;
        case delq:
            X = DeleteQ(Q);
            if ( X!=ERROR ) printf("%d is out\n", X);
            break;
        case end:
            while (Q->Count) printf("%d ", DeleteQ(Q));
            done = 1;
            break;
        }
    }
    system("pause");
    return 0;
}
/*
如果用一个循环数组表示队列，并且只设队列头指针Front，不设尾指针Rear，而是另设Count记录队列中元素个数
：如果队列已满，AddQ函数必须输出“Queue Full”并且返回false；
如果队列是空的，则DeleteQ函数必须输出“Queue Empty”，并且返回ERROR。
*/
bool AddQ( Queue Q, ElementType X ) {
    // 判断队列是否已满 
    if (Q->Count  == Q->MaxSize) {
        printf("Queue Full\n");
        return false;
    }
    Q->Data[Q->Front] = X;
    Q->Front = (Q->Front + 1) % Q->MaxSize;
    ++Q->Count;
    return true;
}
ElementType DeleteQ( Queue Q ) {
    // 判断是否为空 直接利用队列的长度来判断队列是否为空   操作存在问题
    if (!Q->Count) {
        printf("Queue Empty\n");
        return ERROR;
    }
    
    ElementType deElem = (Q->Front - Q->Count + Q->MaxSize) % Q->MaxSize;

    // 所有的循环队列在入队和出队时都要考虑数组下标的循环
    --Q->Count;//表中的元素个数-1
    return Q->Data[deElem];
}


// 细节忽略函数
Operation GetOp() {
    // 思路：
    char input[10];
    scanf("%s", input);
    char Add[] = "Add";
    char Del[] = "Del";
    char End[] = "End";
    if (!strcmp(Add, input)) {
        return addq;
    }
    if (!strcmp(Del, input)) {
        return delq;
    }
    if (!strcmp(End, input)) {
        return end;
    }
}

// 关于VScode  中文名字不能出现最好别用空格  还有许多问题不能检测出来 
// 因为其语法不够健全可能会出现编译出错无法生成链接文件的情况 就比如在这次的枚举变量在使用时出现了问题但是vscode却没有检测出来





// 这一次的修改出现错误的地方：没有遵循队列先进先出的顺序而是将其变成了一个栈···· 后续会更新代码